总结AngularJS 1.x中 scope 的用法
作用域的作用
每条Angular指令都有其作用域,在指令定义时
return
的DDO(Directive Definition Object)里设置。scope
自身是一个对象:有自己的方法和属性。
Angular会通过scope
对象维护所有作用域之间的继承关系。
- 是视图(View)和控制器(Controller)之间的纽带。
创建 controller 时将$scope
作为参数传入,可以将 controller 的数据对应展示到 view 中。
|
|
|
|
作用域的取值
代码示例:plunker演示
|
|
|
|
1. scope: false
(默认值)
指令没有自己的作用域,继承其所在 controller 的作用域,或者rootScope
。
“继承”:在父作用域中修改的变量总是会体现到子作用域中;
“没有自己的作用域”:在指令的模板中可以访问和修改父作用域中的变量。
2. scope: true
指令继承了父作用域,但是创建了新的自己的作用域。
“继承”:在父作用域中修改的变量会体现到子作用域中(在子作用域的同名变量创建之前);
“有自己的作用域”:如果在指令的模板中修改与父作用域同名的变量(仅限于原始数据类型,如
Number
/String
/Boolean
),则访问这个同名变量时只会访问到子作用域的,访问不到父作用域的(和JS原型继承类似)。因为这样会在子作用域中创建一个新的变量。
几点关于JS原型继承的补充:
主要是在childScope
上对基本类型和引用类型的同名变量取值和赋值方面的差别。
对基本类型和引用类型的变量的取值,都会沿着原型链向上查找;
对基本类型的赋值:先查找
childScope
是否有该变量,如果有就更新,如果没有,不会使用原型链查找,而是直接创建该变量然后赋值;后面如果访问这个变量也是访问到childScope
中的而不是parentScope
中的同名变量。对引用类型的赋值:
如果对某对象(或数组、函数)赋值,会在本作用域内查找,有就更新该引用,如果没有也不会使用原型链查找,而是直接新建对象然后赋值,这个和基本类型的赋值一致;
如果对某对象的属性赋值,就会直接查找原型链,找到该对象后直接在原对象上修改,而不会在本地新建。
可能导致的问题:父子作用域之间的通信问题
解决方案:
1)在子作用域中使用$parent.parentScopeProp
访问和修改父作用域的数据;
2)更换数据类型:使用Object(引用类型)而不是原始数据类型,来存储需要共享的数据,访问和修改时使用myObject.myPrimitive
;plunker演示
3)在父作用域中定义回调函数,子作用域调用可实现修改。
适用于调用不传参或参数不为变量的情况:
jsfiddle演示
引申:AngularJS中的“组件”通信方式(计划放到下一篇KM文章里总结)
【重要】
一些常用的内建指令如:ng-repeat
, ng-include
, ng-switch
, ng-controller
的scope
值也是true
。使用它们会创建新的子作用域,如果不注意上面的方法,可能达不到预期的修改父作用域的数据的效果。
3. scope = {...}
对象字面量
创造完全不依赖于父作用域的新的作用域。
好处:便于组件化,可移植性强。
用法:三种前缀(属性匹配)表示法
代码示例:plunkr演示
先看父作用域:
|
|
子作用域:在DDO中对scope
的设置:
|
|